package org.aurora.six;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

/**
 * @author : Aurora
 * @date : 2024/3/28 08:49
 * @description  LockSupport工具类：
 *  主要作用是挂起和唤醒线程，该工具类是创建锁和其他同步类的基础
 */
public class LockSupportAnalysis {
    public static void main(String[] args) {
//        methodParkOne();
//        methodParkTwo();
//        methodParkThree();
//        LockSupportAnalysis lockSupportAnalysis = new LockSupportAnalysis();
//        lockSupportAnalysis.methodParkFour();

        System.out.println(System.currentTimeMillis());
    }
    public static void methodParkOne(){
        //如果调用park方法的线程已经拿到了与LockSupport关联的许可证，
        //  调用LockSupport.park()时会马上返回
        //  否则调用线程会被禁止参与线程的调度，也就是阻塞挂起
        System.out.println("begin park...");
        LockSupport.park();
        System.out.println("end park");//不输出：默认情况下调用线程是不持有许可证的
    }
    public static void methodParkTwo(){
        Thread threadOne = new Thread(() -> {
            System.out.println("Thread one begin park...");
            sleep(1000);
            LockSupport.park();
            System.out.println("Thread One end park");
        });
        Thread threadTwo = new Thread(() -> {
            System.out.println("Thread two start...");
          // sleep(1000);
            //其他线程调用unpark方法并且将当前线程作为参数时，调用park方法而被阻塞的线程会返回
            LockSupport.unpark(threadOne);
            sleep(2000);
            //调用了阻塞线程的interrupt方法，设置了中断标志或者线程被虚假唤醒，阻塞线程也会返回，
            // 且返回时不会抛出InterruptedException异常
            //threadOne.interrupt();
            System.out.println("Thread two unPark one end...");
        });
        threadOne.start();
        threadTwo.start();


    }

    public static void methodParkThree(){
        Thread thread = new Thread(() -> {
            System.out.println("child thread begin park!");
            //调用park方法，挂起自己，只有被中断才会退出循环
            while (!Thread.currentThread().isInterrupted()) {
                LockSupport.park();
            }
            System.out.println("child thread unpark!");
        });
        //启动子线程
        thread.start();
        //主线程休眠1s
        sleep(1000);
        System.out.println("main thread begin unpark!");
        //中断子线程
        thread.interrupt();
    }

    /**
     * void park(Object blocker)
     * 当线程没有持有许可证的情况下调用park方法而被阻塞挂起时，这个blocker对象会被记录到该线程内部
     */
    public void methodParkFour(){
//        LockSupport.park();
        Thread.currentThread();
        LockSupport.park(this);
    }

    public void methodParkFive(){
        long deadLine = 1711688187657L;
        LockSupport.parkUntil(this, deadLine);
    }



    public static void sleep(long mill){
        try {
            Thread.sleep(mill);
        } catch (InterruptedException e) {

        }
    }

    /**
     * 先进先出锁
     */
    class FIFOMutex{
        private final AtomicBoolean locked = new AtomicBoolean(false);
        private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();
        public void lock(){
            boolean wasInterrupted = false;
            Thread current = Thread.currentThread();
            waiters.add(current);
            while(waiters.peek()!=current || !locked.compareAndSet(false,true)){
                LockSupport.park(this);
                if(Thread.interrupted()){
                    //如果park方法是因为被中断而返回，则忽略中断，并且重置中断标志，做个标记，
                    // 然后再次判断当前线程是不是队首元素或者当前锁是否已经被其他线程获取，
                    // 如果是则继续调用park方法挂起自己。
                    wasInterrupted = true;
                }
            }
            waiters.remove();
            if(wasInterrupted){
                current.interrupt();
            }
        }
        public void unlock(){
            locked.set(false);
            LockSupport.unpark(waiters.peek());

        }


    }

}
